package com.cskaoyan.javase.object._6clone._1deep;

/**
 * 深度克隆的问题
 * Object类 当中的clone方法的默认实现,是浅克隆
 *
 * 所谓浅拷贝:
 *      指的是成员变量:
 *      如果是基本数据类型,就直接拷贝一份取值
 *      如果是引用数据类型的话,就直接拷贝一份引用,引用中存储的是地址,于是原先的引用和拷贝引用指向同一个对象
 *          于是得到的拷贝对象和原先的对象,不是完全独立的,还会互相影响
 *          这就是浅拷贝.
 *
 * 浅拷贝得到的对象不是完全独立的,所以需要深拷贝,深克隆,深度克隆
 * 所谓深拷贝就是在浅拷贝的基础上,继续克隆成员变量引用所指向的对象,然后让克隆引用指向克隆后对象
 *      --> 于是克隆对象和原先对象保持完全独立
 *      这就是深拷贝.
 *
 * 注意事项:
 *      1.如果类中有引用数据类型的成员变量,那就需要做深度克隆,来保证两个对象完全独立
 *          如果引用数据类型的成员变量的类中,还有引用数据类型,再做一次深度克隆即可.
 *
 * @since 17:05
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Teacher t = new Teacher(18, 10000, new A(1));
        Teacher cloneTeacher = t.clone();
        // 克隆是得到两个属性取值完全一致,但相互独立的两个对象
        t.age = 100;
        System.out.println(cloneTeacher.age);

        t.a.num = 2;
        System.out.println(cloneTeacher.a.num);
    }
}

class Teacher implements Cloneable {
    int age;
    double salary;
    A a;

    public Teacher() {
    }

    public Teacher(int age, double salary, A a) {
        this.age = age;
        this.salary = salary;
        this.a = a;
    }

    // 修改Teacher类的clone方法实现,完成深度克隆
    @Override
    protected Teacher clone() throws CloneNotSupportedException {
        // 1.深克隆是在浅克隆的基础上完成的,这个对象就是需要返回的对象
        Teacher cloneTeacher = (Teacher) super.clone();
        // 2.克隆一份a对象
        A cloneA = this.a.clone();
        // 3.将克隆后的Teacher对象的拷贝a引用指向拷贝a对象
        cloneTeacher.a = cloneA;
        return cloneTeacher;
    }
}

class A implements Cloneable {
    int num;

    public A() {
    }

    public A(int num) {
        this.num = num;
    }

    @Override
    protected A clone() throws CloneNotSupportedException {
        return (A) super.clone();
    }
}